package com.mark.spring.annotation.aop.log;

import com.mark.spring.annotation.aop.log.ServiceLog;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.util.Arrays;

/**
 * @Description: 日志切面
 * @Author: Mark
 * @CreateDate: 2019/9/2 22:03
 * @Version: 3.00.001
 * @Copyright : 豆浆油条个人非正式工作室
 */
@Component
@Aspect
public class LogAspects {

    /**
     * 抽取公共的切入点表达式
     *
     * 例： execution (* com.sample.service..*.*(..))
     * 整个表达式可以分为五个部分：
     * 1、execution():：表达式主体。
     * 2、第一个*号：表示返回类型， *号表示所有的类型。
     * 3、包名：表示需要拦截的包名，后面的两个句点表示当前包和当前包的所有子包，com.sample.service包、子孙包下所有类的方法。
     * 4、第二个*号：表示类名，*号表示所有的类。
     * 5、*(..)：最后这个星号表示方法名，*号表示所有的方法，后面括弧里面表示方法的参数，两个句点表示任何参数
     */
    @Pointcut("execution(public * com.mark.spring.annotation.aop..*.*(..))")
    public void pointCut(){}

    @Before("pointCut()")
    public void logStart(JoinPoint joinPoint){
        Object[] args = joinPoint.getArgs();
        System.out.println(""+joinPoint.getSignature().getName()+"运行。。。@Before:参数列表是：{"+ Arrays.asList(args)+"}");
    }

    @After("pointCut()")
    public void logEnd(JoinPoint joinPoint){
        System.out.println(""+joinPoint.getSignature().getName()+"结束。。。@After");
    }

    //JoinPoint一定要出现在参数表的第一位
    @AfterReturning(value="pointCut()",returning="result")
    public void logReturn(JoinPoint joinPoint, Object result) throws ClassNotFoundException {
        String targetClassName = joinPoint.getTarget().getClass().getName();
        String methodName = joinPoint.getSignature().getName();
        Object[] args = joinPoint.getArgs();
        Class<?> targetClass = Class.forName(targetClassName);
        Method[] methods = targetClass.getMethods();
        for(Method method : methods){
            if(method.getName().equals(methodName)){
                Class<?>[] parameterTypes = method.getParameterTypes();
                //获取自定义的日志注解实例
                ServiceLog serviceLog = method.getAnnotation(ServiceLog.class);
                if(parameterTypes.length == args.length && null != serviceLog){
                    String des = serviceLog.des();
                    System.out.println(des);
                }
            }
        }

        System.out.println(""+joinPoint.getSignature().getName()+"正常返回。。。@AfterReturning:运行结果：{"+result+"}");
    }

    @AfterThrowing(value="pointCut()",throwing="exception")
    public void logException(JoinPoint joinPoint,Exception exception){
        System.out.println(""+joinPoint.getSignature().getName()+"异常。。。异常信息：{"+exception+"}");
    }
}
